package com.hexiang.web;

import com.hexiang.dao.BookRepository;
import com.hexiang.domain.Book;
import com.hexiang.error.BookNotFoundException;
import com.hexiang.error.BookUnSupportedFieldPatchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 书籍控制器
 *
 * @author h01463
 */
@RestController
public class BookController {

    @Autowired
    private BookRepository repository;

    /**
     * 查询所有书籍
     *
     * @return
     */
    @GetMapping("/books")
    List<Book> findAll() {
        return repository.findAll();
    }

    /**
     * 新增书籍
     *
     * @param newBook 书籍
     * @return
     */
    @PostMapping("/books")
    @ResponseStatus(HttpStatus.CREATED)
    Book newBook(@RequestBody Book newBook) {
        return repository.save(newBook);
    }

    /**
     * 根据id查询书籍
     *
     * @param id 书籍id
     * @return
     */
    @GetMapping("/books/{id}")
    Book findOne(@PathVariable Long id) {
        return repository.findById(id).orElseThrow(() -> new BookNotFoundException(id));
    }

    /**
     * 根据id修改书籍
     *
     * @param newBook 书籍对象
     * @param id      书籍id
     * @return
     */
    @PutMapping("/books/{id}")
    Book saveOrUpdate(@RequestBody Book newBook, @PathVariable Long id) {

        return repository.findById(id).map(x -> {
            x.setName(newBook.getName());
            x.setAuthor(newBook.getAuthor());
            x.setPrice(newBook.getPrice());
            return repository.save(x);
        }).orElseGet(() -> {
            newBook.setId(id);
            return repository.save(newBook);
        });
    }

    @PatchMapping("/books/{id}")
    Book patch(@RequestBody Map<String, String> update, @PathVariable Long id) {

        return repository.findById(id).map(x -> {

            String author = update.get("author");
            if (!StringUtils.isEmpty(author)) {
                x.setAuthor(author);

                // better create a custom method to update a value = :newValue where id = :id
                return repository.save(x);
            } else {
                throw new BookUnSupportedFieldPatchException(update.keySet());
            }

        }).orElseGet(() -> {
            throw new BookNotFoundException(id);
        });

    }

    @DeleteMapping("/books/{id}")
    void deleteBook(@PathVariable Long id) {
        repository.deleteById(id);
    }

}
